
/*
 * 文件名：ExcelUtil.java
 * 修改人：chenliang
 * 修改时间：2018年8月11日
 * 修改内容：
 */

package com.kalvan.web.excel;

import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.kalvan.core.exception.BizException;
import com.kalvan.core.utils.ValidationUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class ExcelUtil {

    /**
     * excel下载
     *
     * @param fileName  文件名
     * @param response
     * @param pojoClass java对象
     * @param data      数据集合
     * @throws Exception
     */
    public static void download(String fileName, HttpServletResponse response, Class<? extends BaseRowModel> pojoClass, List data) throws Exception {
        fileName = fileName + ".xlsx";
        response.setContentType("multipart/form-data");
        response.setHeader("filename", URLEncoder.encode(fileName, "utf-8"));
        OutputStream out = response.getOutputStream();
        ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
        Sheet sheet = new Sheet(1, 0, pojoClass);
        writer.write(data, sheet);
        writer.finish();
        out.flush();
    }


    /**
     * 模板文件下载 相对路径 /static/template/xx.file
     *
     * @param filepath
     * @param response
     * @throws Exception
     * @see
     */
    public static void downloadTemplate(String filepath, HttpServletResponse response) throws Exception {
        String basePath = new File(ExcelUtil.class.getResource("/").getPath()).toString();
        filepath = basePath + File.separator + filepath;
        String fileName = filepath.substring(filepath.lastIndexOf("/") + 1);
        response.setContentType("multipart/form-data");
        response.setHeader("filename", URLEncoder.encode(fileName, "utf-8"));
        OutputStream out = response.getOutputStream();
        try {
            InputStream is = new FileInputStream(new File(filepath));
            BufferedInputStream bis = new BufferedInputStream(is);
            byte[] b = new byte[1024];
            int len = 0;
            while ((len = bis.read(b)) != -1) {
                out.write(b, 0, len);
            }
            out.flush();
            bis.close();
            is.close();
            out.close();
        } catch (Exception e) {
            log.error("下载模板文件异常", e);
            throw new BizException("下载模板文件异常");
        }

    }

    /**
     * excel 导入
     *
     * @param file       上传excel文件
     * @param sheet      sheet 页从1开始
     * @param headerRows 表头占前几行 从0 开始
     * @param pojoClass  转换成java对象
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> List<T> importExcel(MultipartFile file, Integer sheet, Integer headerRows, Class<? extends BaseRowModel> pojoClass)
            throws Exception {
        if (file == null) {
            throw new BizException("导入文件为空");
        }

        InputStream inputStream = file.getInputStream();
        final List<T> rows = new ArrayList();
        // 解析每行结果在listener中处理
        AnalysisEventListener analysisEventListener = new AnalysisEventListener() {
            @Override
            public void invoke(Object object, AnalysisContext context) {
                //验证导入对象
                String errorMsg = ValidationUtil.validation(object, null);
                if (StringUtils.isNotBlank(errorMsg)) {
                    throw new BizException(String.format("第%s行数据有误:%s", rows.size(), errorMsg));
                }
                rows.add((T) object);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
            }
        };
        // TODO 要支持xls 和xlsx
        ExcelReader excelReader = new ExcelReader(inputStream, ExcelTypeEnum.XLS, (Object) null, analysisEventListener, true);
        excelReader.read(new Sheet(sheet, headerRows, pojoClass));
        return rows;
    }

}
